package com.xhh.interview.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.utils.thread.ThreadLocalUtil;
import com.xhh.apis.check.ICheckClient;
import com.xhh.apis.user.IUserClient;
import com.xhh.common.aliyun.util.SMSUtils;
import com.xhh.common.constants.CheckedConstants;
import com.xhh.common.constants.InterviewConstants;
import com.xhh.common.constants.ReapplyConstants;
import com.xhh.interview.mapper.InterviewMapper;
import com.xhh.interview.service.InterviewService;
import com.xhh.model.check.vos.CheckedVo;
import com.xhh.model.common.dtos.PageResponseResult;
import com.xhh.model.common.dtos.ResponseResult;
import com.xhh.model.common.enums.AppHttpCodeEnum;
import com.xhh.model.interview.dtos.InterviewPageDto;
import com.xhh.model.interview.dtos.SendNoticeDto;
import com.xhh.model.interview.dtos.UpdateStatusDto;
import com.xhh.model.interview.pojos.Interview;
import com.xhh.model.interview.vos.InterviewVo;
import com.xhh.model.reapply.pojos.Preapply;
import com.xhh.model.user.pojos.Student;
import com.xhh.model.user.pojos.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xhh
 * @since 2024-08-07
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InterviewServiceImpl extends ServiceImpl<InterviewMapper, Interview> implements InterviewService {

    private final IUserClient userClient;
    private final ICheckClient checkClient;
    private final RabbitTemplate rabbitTemplate;

    /**
     * 发送复试通知
     * @param dto
     * @return
     */
    @Override
    public ResponseResult notice(SendNoticeDto dto) {
        // 1. 校验参数
        if (StrUtil.isEmpty(dto.getTitle()) || StrUtil.isEmpty(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 内容长度不能超过200
        if (dto.getContent().length() > 200) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_LENGTH_MUST_IN_200);
        }
        User user = ThreadLocalUtil.getUser();
        // 校验身份
        ResponseResult response = checkClient.checkIdentity(user.getId());
        String json = (String) response.getData();
        CheckedVo checked = JSONObject.parseObject(json, CheckedVo.class);
        if (!checked.getIdentityCode().equals(CheckedConstants.SCHOOL_IDENTITY_CODE)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        // 获取用户名
        ResponseResult result = userClient.getUserById(user.getId());
        String jsonStr = JSON.toJSONString(result.getData());
        user = JSONObject.parseObject(jsonStr, User.class);
        // 2. 构建插入条件
        Interview interview = new Interview();
        interview.setPId(dto.getId());
        interview.setTitle(dto.getTitle());
        interview.setContent(dto.getContent());
        interview.setSendTime(new Date());
        interview.setUnityCode(dto.getChoiceUnityCode());
        interview.setFaultyCode(dto.getChoiceFaultyCode());
        interview.setFaultyName(dto.getChoiceFaultyName());
        interview.setMajorCode(dto.getChoiceMajorCode());
        interview.setMajorName(dto.getChoiceMajorName());
        interview.setAccount(user.getUsername());
        interview.setStuCode(dto.getStuCode());
        interview.setAccountPhone(dto.getPhone());
        interview.setStatus(InterviewConstants.NOTICE_STATUS_INIT);
        save(interview);
        // 发送短信通知的消息
        String ufmName = dto.getChoiceFaultyName() + dto.getChoiceMajorName() + "专业";
        HashMap<String, String> msg = new HashMap<>();
        msg.put("phoneNumbers", dto.getPhone());
        msg.put("stuName", dto.getStuName());
        msg.put("ufmName", ufmName);
        msg.put("msg", dto.getContent());
        try {
            rabbitTemplate.convertAndSend(
                    InterviewConstants.EXCHANGE_NAME,
                    InterviewConstants.SEND_MESSAGE_KEY,
                    msg
            );
        } catch (AmqpException e) {
            log.error("发送短信通知的消息发送失败, 异常信息:{}", e);
        }
        // 异步通知调剂志愿微服务删除备选库记录
        try {
            log.info("备选库id：{}, 参数类型是：{}", dto.getId(), dto.getId().getClass());
            rabbitTemplate.convertAndSend(
                    ReapplyConstants.EXCHANGE_NAME,
                    ReapplyConstants.DELETE_PREAPPLY_KEY,
                    dto.getId()
            );
        } catch (AmqpException e) {
            log.error("删除备选库记录的消息发送失败, 备选库id：{}", dto.getId(), e);
        }
        // 3. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查看复试通知
     * @return
     */
    @Override
    public ResponseResult getNotice() {
        // 1. 获取登录用户id
        User user = ThreadLocalUtil.getUser();
        // 2. 校验身份
        ResponseResult response = checkClient.checkIdentity(user.getId());
        String json = (String) response.getData();
        CheckedVo checked = JSONObject.parseObject(json, CheckedVo.class);
        if (!checked.getIdentityCode().equals(CheckedConstants.STUDENT_IDENTITY_CODE)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        // 3. 查询复试通知表
        // 3.1 获取考生的准考证号
        ResponseResult result = userClient.getStuByUId(user.getId());
        String string = JSON.toJSONString(result.getData());
        Student student = JSONObject.parseObject(string, Student.class);
        // 3.2 构建查询条件
        List<Interview> list = lambdaQuery().eq(Interview::getStuCode, student.getStuNo()).list();
//        if (CollUtil.isEmpty(list)) {
//            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
//        }
        // 4. 返回结果
        return ResponseResult.okResult(list);
    }

    /**
     * 接收或者拒绝复试通知
     * @param dto
     * @return
     */
    @Override
    public ResponseResult markNoticeStatusAcceptOrRefuse(UpdateStatusDto dto) {
        // 1. 校验参数
        if (dto == null || dto.getId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 查看复试通知状态是否是同意，如果是同意则不可再修改状态
        Interview interview = getById(dto.getId());
        if (interview.getStatus().equals(InterviewConstants.NOTICE_STATUS_AGREE)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.INTERVIEW_NOTICE_ALREADY_ACCEPTED);
        }
        // 2. 更新复试通知表状态
        // 同意
        if (dto.getOperation().equals(InterviewConstants.NOTICE_OPERATION_ACCEPT)) {
            lambdaUpdate()
                    .set(Interview::getStatus, InterviewConstants.NOTICE_STATUS_AGREE)
                    .set(Interview::getReplyTime, new Date())
                    .eq(Interview::getId, dto.getId())
                    .update();
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        // 拒绝
        if (dto.getOperation().equals(InterviewConstants.NOTICE_OPERATION_REFUSE)) {
            lambdaUpdate()
                    .set(Interview::getStatus, InterviewConstants.NOTICE_STATUS_DISAGREE)
                    .set(Interview::getReplyTime, new Date())
                    .eq(Interview::getId, dto.getId())
                    .update();
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        // 3. 返回结果
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }

    /**
     * 分页条件查询复试通知
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getNoticeByPageAndCondition(InterviewPageDto dto) {
        // 1. 分页参数校验
        dto.checkParam();
        // 校验用户身份
        User user = ThreadLocalUtil.getUser();
        ResponseResult response = checkClient.checkIdentity(user.getId());
        String json = (String) response.getData();
        CheckedVo checked = JSONObject.parseObject(json, CheckedVo.class);
        if (!checked.getIdentityCode().equals(CheckedConstants.SCHOOL_IDENTITY_CODE)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        // 获取用户名
        ResponseResult result = userClient.getUserById(user.getId());
        String s = JSON.toJSONString(result.getData());
        user = JSONObject.parseObject(s, User.class);
        // 2. 构建分页查询参数
        Page<Interview> page = new Page<>(dto.getPage(), dto.getSize());
        page = lambdaQuery()
                .eq(Interview::getAccount, user.getUsername())
                .eq(StrUtil.isNotEmpty(dto.getChoiceFaultyCode()), Interview::getFaultyCode, dto.getChoiceFaultyCode())
                .eq(StrUtil.isNotEmpty(dto.getChoiceMajorCode()), Interview::getMajorCode, dto.getChoiceMajorCode())
                .eq(StrUtil.isNotEmpty(dto.getStatus()), Interview::getStatus, dto.getStatus())
                .page(page);
        // 处理返回结果
        List<Interview> records = page.getRecords();
        List<InterviewVo> list = records.stream().map(record -> {
            // 根据准考证号获取考生姓名
            Student stu = getStuByCode(record);
            InterviewVo vo = BeanUtil.copyProperties(record, InterviewVo.class);
            vo.setStuName(stu.getName());
            return vo;
        }).collect(Collectors.toList());
        // 3. 返回结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        responseResult.setData(list);
        return responseResult;
    }

    private Student getStuByCode(Interview record) {
        ResponseResult res = userClient.getStuByCode(record.getStuCode());
        String jsonString = JSON.toJSONString(res.getData());
        return JSONObject.parseObject(jsonString, Student.class);
    }
}
